import re
import datetime
from django.contrib.auth import get_user_model
from django.db.models import F
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings
from apps.sales_man.models import SalesMan, ApplicantList
from core.tools.serializers import BankCodeSerializer, BankCode
from core.tools.card_verify import verify_card
from core.tools.encryption import md5
from core.tools.models import ShortMsg
from finance_c2c.settings import REGEX_MOBILE, API_DATETIME_FORMAT, API_DATE_FORMAT_POINT
from .models import LevelDesc, Menus, PublicAccount, UserProfileExtend
from .utils import jwt_payload_handler
from apps.supply_order.models import PopularQrCode
from apps.supply_order.serializers import CompanySerializers
from core.wchat.models import WxUserInfo
from core.wchat.WXInstance import KLBWxBase as wx_base
from dateutil.relativedelta import relativedelta
from wechatpy.exceptions import WeChatOAuthException
from core.tools.encryption import md5
from apps.coffee.config import system_user

jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
UserModel = get_user_model()


class SalesManSerializer(serializers.ModelSerializer):
    class Meta:
        model = SalesMan
        fields = ("card", "tel", "name")


class BaseClickProductSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=16, label="申请人姓名", help_text="申请人姓名", error_messages={
        "blank": "姓名不能为空",
        "max_length": "最长16个字符"
    })

    product = serializers.IntegerField(label="产品id", error_messages={
        "blank": "请填写产品id"
    })

    account = serializers.CharField(max_length=16, label="申请人账号", error_messages={
        "blank": "请填写申请人账号"
    })

    def validate(self, attrs):
        salesman = attrs.pop("account")
        attrs["salesman"] = salesman
        # attrs.pop("ver_code")
        attrs.pop("product")
        return attrs

    def validate_account(self, account):
        salesman = SalesMan.objects.filter(account=account)
        if salesman.exists():
            return salesman.first()
            # self.initial_data["salesman"] = salesman
            # del self.initial_data["account"]
        else:
            raise serializers.ValidationError("参数错误")

    def create(self, validated_data):
        obj, created = ApplicantList.objects.get_or_create(**validated_data)
        return obj

    def update(self, instance, validated_data):
        pass


class ClickProductSerializer(BaseClickProductSerializer):
    tel = serializers.CharField(label="手机号", max_length=11, min_length=11, help_text="手机号", error_messages={
        "blank": "手机号不能为空",
        "max_length": "请正确填写手机号",
        "min_length": "请正确填写手机号"
    })
    card = serializers.CharField(max_length=20, label="申请人身份证", help_text="申请人身份证", error_messages={
        "blank": "身份证不能为空",
        "max_length": "身份证最长20个字符"
    })

    def validate_card(self, card):
        if not verify_card(card):
            raise serializers.ValidationError("请检查身份证号")
        return card


class VerClickProductSerializer(ClickProductSerializer):
    ver_code = serializers.CharField(required=True, label="验证码", help_text="验证码", max_length=4, min_length=4,
                                     error_messages={
                                         "blank": "验证码不能为空",
                                         "max_length": "验证码只能是4位数字",
                                         "min_length": "验证码只能是4位数字"
                                     })

    def validate_ver_code(self, code):
        # return code
        tel = self.initial_data["tel"]
        if info.exists():
            info_obj = info.first()
            if info_obj.status:
                info_obj.status = False
                info_obj.save()
            else:
                pass
            return code
        else:
            raise serializers.ValidationError("验证码不正确")

    def validate(self, attrs):
        salesman = attrs.pop("account")
        attrs["salesman"] = salesman
        attrs.pop("ver_code")
        attrs.pop("product")
        return attrs


class NoCodeSerializer(serializers.Serializer):
    tel = serializers.CharField(label="手机号", max_length=11, min_length=11, help_text="手机号", error_messages={
        "blank": "手机号不能为空",
        "max_length": "请正确填写手机号",
        "min_length": "请正确填写手机号"
    })
    card = serializers.CharField(max_length=20, label="申请人身份证", help_text="申请人身份证", error_messages={
        "blank": "身份证不能为空",
        "max_length": "身份证最长20个字符"
    })

    def validate_card(self, card):
        if not verify_card(card):
            raise serializers.ValidationError("请检查身份证号")
        return card

    def create(self, validated_data):
        pass

    def update(self, instance, validated_data):
        pass


class TelCodeSerializer(NoCodeSerializer):
    ver_code = serializers.CharField(required=True, label="验证码", help_text="验证码", max_length=4, min_length=4,
                                     error_messages={
                                         "blank": "验证码不能为空",
                                         "max_length": "验证码只能是4位数字",
                                         "min_length": "验证码只能是4位数字"
                                     })

    def validate_ver_code(self, code):
        tel = self.initial_data["tel"]
        info = ShortMsg.objects.filter(code=code, tel=tel)
        if info.exists():
            info_obj = info.first()
            if info_obj.status:
                info_obj.status = False
                info_obj.save()
                return code
            else:
                raise serializers.ValidationError("验证码已被使用过了")
        else:
            raise serializers.ValidationError("验证码不正确")


class VisitListSerializer(serializers.Serializer):
    account = serializers.CharField(label="账号", max_length=16, min_length=3, help_text="账号", error_messages={
        "blank": "账号不能为空",
        "max_length": "账号过长",
        "min_length": "账号过短"
    })

    password = serializers.CharField(label="密码", max_length=16, min_length=8, help_text="密码", error_messages={
        "blank": "密码不能为空",
        "max_length": "密码过长",
        "min_length": "密码过短"
    })

    def validate(self, attrs):
        """
        :param attrs:
        :return:
        """
        account = attrs.get("account")
        password = attrs.get("password")
        password = md5(md5(password))
        try:
            salesman = SalesMan.objects.get(account=account, password=password)
        except Exception as e:
            print(e)
            raise serializers.ValidationError("账号密码错误")
        return salesman

    def create(self, validated_data):
        pass

    def update(self, instance, validated_data):
        pass


# 登录注册
class MyLoginSerializer(serializers.Serializer):
    mobile = serializers.CharField(label="手机号", write_only=True, max_length=11, min_length=11, help_text="手机号",
                                   required=True, error_messages={
            "required": "手机号为必填项",
            "blank": "账号不能为空",
            "max_length": "账号过长",
            "min_length": "账号过短"
        })
    code = serializers.CharField(label="验证码", write_only=True, max_length=4, min_length=4, help_text="验证码",
                                 required=True, error_messages={
            "required": "手机号为必填项",
            "blank": "验证码不能为空",
            "max_length": "验证码过长",
            "min_length": "验证码过短"
        })
    openid_e = serializers.CharField(label="openid_e", write_only=True, required=False, allow_null=True,
                                     allow_blank=True)

    def validate_openid_e(self, openid_e):
        if openid_e:
            try:
                return WxUserInfo.objects.get(openid_e=openid_e)
            except Exception as e:
                print(e)
                raise serializers.ValidationError("微信openid错误")
        else:
            return None

    def validate_mobile(self, mobile):
        if re.match(REGEX_MOBILE, mobile):
            return mobile
        else:
            raise serializers.ValidationError("手机号不合法")

    def validate_code(self, code):
        mobile = self.initial_data["mobile"]
        info = ShortMsg.objects.filter(code=code, tel=mobile)
        if info.exists():
            info_obj = info.first()
            if info_obj.status:
                info_obj.status = False
                info_obj.save()
                return code
            else:
                raise serializers.ValidationError("验证码已被使用过了")
        else:
            raise serializers.ValidationError("验证码不正确")

    def create(self, validated_data):
        mobile = validated_data["mobile"]
        try:
            user = UserModel.objects.get(mobile=mobile)
        except UserModel.DoesNotExist as e:
            user = UserModel.objects.create(
                mobile=mobile,
                level=LevelDesc.objects.get(level=1),
                username=mobile,
            )
        print(validated_data.get("openid_e"))
        if validated_data.get("openid_e"):
            user.wx_user = validated_data["openid_e"]
            user.save()
        from apps.coffee.models import GiveRecord
        GiveRecord.objects.new_user_login(user)
        return user

    def update(self, instance, validated_data):
        pass

    def validate(self, attrs):
        user = self.create(attrs)
        payload = jwt_payload_handler(self, user)
        token = jwt_encode_handler(payload)
        setattr(self, 'object', {"user": user, "token": token})
        return {
            'token': token,
            'user': user
        }

    class Meta:
        fields = ("mobile", "code", "openid_e")


# 微信登录
class WXLoginSerializer(serializers.Serializer):
    scope = serializers.CharField(label="scope", allow_blank=True, allow_null=True, required=False, default=None)
    code = serializers.CharField(label="code", max_length=64, min_length=32)

    def validate_scope(self, scope):
        return scope

    def validate_code(self, code):
        scope = self.initial_data.get("scope")
        if scope:
            weChatOAuth = wx_base.get_we_chat_OAuth("", scope=scope)
        else:
            weChatOAuth = wx_base.get_we_chat_OAuth("")
        setattr(self, "weChatOAuth", weChatOAuth)
        try:
            res = self.weChatOAuth.fetch_access_token(code)
        except WeChatOAuthException as e:
            raise serializers.ValidationError(e.errcode)
        print(res)
        return res

    def validate(self, attrs):
        self.create(attrs)
        return attrs

    def create(self, validated_data):
        res = validated_data["code"]
        access_token = res.get("access_token")
        openid = res.get("openid")
        wx_user_info, created = WxUserInfo.objects.get_or_create(openid=openid, openid_e=md5(md5(openid)))
        if validated_data["scope"] != "snsapi_base":
            user_info = self.weChatOAuth.get_user_info(openid, access_token)
            print(user_info, "微信用户信息")
            wx_user_info.update_info(user_info)
        if hasattr(wx_user_info, "userprofile"):
            user = wx_user_info.userprofile
            payload = jwt_payload_handler(self, user)
            token = jwt_encode_handler(payload)
            setattr(self, 'object', {"user": user, "token": token})
        else:
            setattr(self, 'object', {"openid_e": wx_user_info.openid_e})
        return wx_user_info

    def update(self, instance, validated_data):
        pass

    class Meta:
        fields = ("scope", "code",)


# 团队详情包含各等级的人数
class TeamDetailsSerializers(serializers.Serializer):
    level_desc = serializers.CharField(read_only=True, label="描述", help_text="描述")
    num = serializers.IntegerField(read_only=True, label="描述", help_text="描述")

    class Meta:
        fields = ("level_desc", "num", "level3", "level4")


class UserImgSerializers(serializers.ModelSerializer):
    header_img = serializers.SerializerMethodField(read_only=True, label="头像")

    def get_header_img(self, instance):
        header_img = instance.header_img
        if header_img:
            request = self.context.get('request', None)
            if request is not None:
                header_img = request.build_absolute_uri(header_img.url)
        else:
            if instance.wx_user and instance.wx_user.head_url:
                if "http://" in instance.wx_user.head_url:
                    return instance.wx_user.head_url.replace("http://", "https://")
                else:
                    return instance.wx_user.head_url
            header_img = "https://shop.kalaibao.com/h5/default_header.png"
        return header_img

    class Meta:
        model = UserModel
        fields = ("header_img",)


# 团队人员列表
class TeamSerializers(UserImgSerializers):
    create_time = serializers.DateTimeField(read_only=True, format=API_DATETIME_FORMAT, label="注册时间")
    user_code = serializers.SerializerMethodField(read_only=True, label="推荐码")

    def get_user_code(self, obj):
        return obj.id

    class Meta:
        model = UserModel
        fields = ("name", "create_time", "user_code", "header_img")


# 绑定上级
class BandLeaderSerializers(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    leader_code = serializers.IntegerField(write_only=False, required=True, allow_null=True, label="推荐码",
                                           error_messages={
                                               "required": "该字段必填",
                                           })

    class Meta:
        model = UserModel
        fields = ("user", "leader_code",)

    @classmethod
    def tai_back_door(cls, instance):
        from apps.supply_order.models import BackDoorTai
        # 如果在白名单
        if BackDoorTai.objects.filter(mobile=instance.mobile).exists():
            now_day = datetime.date.today()
            instance.oil_flag = True
            instance.oil_flag_expiry_date = now_day + relativedelta(months=3)
            instance.level = LevelDesc.objects.get(level=2)
        else:
            # 如果没在白名单 没有加油权益 没有会员权益
            instance.level = LevelDesc.objects.get(level=1)
        return instance

    def validate_leader_code(self, leader_code):
        print("leader_code", leader_code)
        try:
            UserModel.objects.get(id=leader_code)
            return leader_code
        except UserModel.DoesNotExist as e:
            user_instance = UserModel.objects.get(mobile=system_user)
            return user_instance.id

    def update(self, instance, validated_data):
        print(validated_data, "validated_data")
        leader_code = validated_data["leader_code"]
        leader = UserModel.objects.get(id=leader_code)
        if instance.leader:
            pass
        else:
            # 如果标记了vip 下面的用户注册的都是会员
            now_time = datetime.datetime.now()
            now_day = datetime.date.today()
            # 一层
            if leader.lower_is_vip:
                # 如果没有结束时间 就一直注册成为会员
                if not leader.lower_vip_end_time:
                    leader.lower_num = F("lower_num") + 1
                    leader.save()
                    instance.level = LevelDesc.objects.get(level=2)
                # 如果会员开放日期大于当前日期
                elif leader.lower_vip_end_time and leader.lower_vip_end_time > now_time:
                    leader.lower_num = F("lower_num") + 1
                    leader.save()
                    instance.level = LevelDesc.objects.get(level=2)
                else:
                    pass
            # 两层
            elif leader.leader and leader.leader.lower_is_vip:
                # 如果没有结束时间 就一直注册成为会员
                if not leader.leader.lower_vip_end_time:
                    leader.lower_num = F("lower_num") + 1
                    leader.save()
                    instance.level = LevelDesc.objects.get(level=2)
                # 如果会员开放日期大于当前日期
                elif leader.leader.lower_vip_end_time and leader.leader.lower_vip_end_time > now_time:
                    leader.lower_num = F("lower_num") + 1
                    leader.save()
                    instance.level = LevelDesc.objects.get(level=2)
                else:
                    pass
            # 新增 所有人都是会员
            else:
                instance.level = LevelDesc.objects.get(level=2)
                instance.oil_flag = True
                instance.oil_flag_expiry_date = now_day + relativedelta(months=12)
            # 如果上级有对应的微信公众号
            if leader.public_account:
                instance.public_account = leader.public_account
            instance.leader = leader
            instance.company = leader.company  # 同一个公司
            instance.oil_flag = True
            instance.oil_flag_expiry_date = now_day + relativedelta(years=999)
            instance.save()
            instance.refresh_from_db()
        return instance


# 展示上级
class LeaderSerializers(serializers.ModelSerializer):
    name = serializers.CharField(read_only=True)
    id = serializers.CharField(read_only=True)

    class Meta:
        model = UserModel
        fields = ("id", "name",)


# 更新银行卡号
class BaseBankCardNoSerializers(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    bank_card_no = serializers.CharField(max_length=20, label="银行卡号", error_messages={"blank": "请输入银行卡号"})
    bank = serializers.PrimaryKeyRelatedField(label="银行id", error_messages={"blank": "银行id不能为空"}, write_only=True,
                                              queryset=BankCode.objects.all())
    real_name = serializers.CharField(required=True, label="真实姓名", error_messages={"blank": "必填项", "required": "必填项"}, )

    class Meta:
        model = UserModel
        fields = ("user", "bank_card_no", "bank", 'real_name')


# 更新用户的真实姓名
class NameSerializers(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    name = serializers.CharField(max_length=16, label="姓名", error_messages={"blank": "请输入姓名"})

    class Meta:
        model = UserModel
        fields = ("user", "name",)


# 绑定银行卡
class BankCardNoSerializers(BaseBankCardNoSerializers):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    # bank_card_no = serializers.CharField(max_length=20, label="银行卡号")
    mobile = serializers.CharField(allow_blank=False, required=True, label="手机号")
    sms_code = serializers.CharField(write_only=True, allow_blank=False, required=True, label="短信验证码",
                                     help_text="短信验证码")

    class Meta:
        model = UserModel
        fields = ("user", "mobile", "sms_code", "bank_card_no", "bank", "real_name")

    # 验证
    def validate_mobile(self, mobile):
        user = self.initial_data["user"] if self.initial_data.get("user") else self.context["request"].user
        if user.bank_card_no:
            if re.match(REGEX_MOBILE, mobile):
                return mobile
            else:
                raise serializers.ValidationError("手机号格式错误")
        else:
            return mobile

    # 验证验证码
    def validate_sms_code(self, sms_code):
        user = self.context["request"].user
        mobile = self.initial_data["mobile"]
        if user.bank_card_no:
            status, msg = ShortMsg.objects.sms_code(sms_code, mobile)
            if status:
                return sms_code
            else:
                raise serializers.ValidationError(msg)
        else:
            return sms_code

    def validate(self, attrs):
        del attrs["mobile"]
        del attrs["sms_code"]
        return attrs


# 更新手机号
class TelSerializers(serializers.ModelSerializer):
    mobile = serializers.CharField(allow_blank=False, required=True, label="手机号", help_text="手机验证码")
    sms_code = serializers.CharField(write_only=True, allow_blank=False, required=True, label="短信验证码",
                                     help_text="短信验证码")

    class Meta:
        model = UserModel
        fields = ("mobile", "sms_code")

    # 验证
    def validate_mobile(self, mobile):
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号格式错误")
        user = self.context["request"].user
        if user.mobile == mobile:
            raise serializers.ValidationError("手机号没有发生变化")
        else:
            if UserModel.objects.filter(mobile=mobile).exists():
                raise serializers.ValidationError("此手机号已经被其他人注册了")
            else:
                return mobile

    # 验证验证码
    def validate_sms_code(self, sms_code):
        mobile = self.initial_data["mobile"]
        status, msg = ShortMsg.objects.sms_code(sms_code, mobile)
        if status:
            return sms_code
        else:
            raise serializers.ValidationError(msg)

    def validate(self, attrs):
        del attrs["sms_code"]
        return attrs

    def update(self, instance, validated_data):
        instance.mobile = validated_data["mobile"]
        instance.username = validated_data["mobile"]
        instance.save()
        return instance
        # payload = jwt_payload_handler(self, instance)
        # token = jwt_encode_handler(payload)
        # setattr(self, 'object', {"user": instance, "token": token})


# 用户信息
class MyInfoSerializer(UserImgSerializers):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault)
    leader_name = serializers.SerializerMethodField(read_only=True)
    real_name = serializers.SerializerMethodField(read_only=True)
    bank_card_no = serializers.SerializerMethodField(read_only=True)
    bank = serializers.SerializerMethodField(read_only=True)
    name = serializers.SerializerMethodField(read_only=True)
    leader = serializers.SerializerMethodField(read_only=True)
    user_id = serializers.SerializerMethodField(read_only=True)
    user_code = serializers.SerializerMethodField(read_only=True)
    is_vip = serializers.SerializerMethodField(read_only=True, label="是否是会员")
    level_desc = serializers.SerializerMethodField(read_only=True, label="是否是会员")
    public_account = serializers.SerializerMethodField(read_only=True, label="公众号信息")
    show_qr_code = serializers.BooleanField(read_only=True, label="展示二维码")
    show_public_account = serializers.SerializerMethodField(read_only=True, label="展示关注公众号")
    company = CompanySerializers(many=False)
    oil_flag_expiry_date = serializers.DateField(format=API_DATE_FORMAT_POINT, read_only=True)
    oil_flag = serializers.SerializerMethodField()

    def get_oil_flag(self, instance):
        if instance.oil_flag_expiry_date and datetime.date.today() <= instance.oil_flag_expiry_date:
            return True
        else:
            return False

    # oil_expiry_sign = serializers.BooleanField(label="有效期标识", read_only=True)

    # def get_oil_expiry_sign(self, instance):
    #     if instance.oil_flag_expiry_date:
    #         if datetime.date.today() > instance.oil_flag_expiry_date:
    #             return True
    #         else:
    #             return False
    #     else:
    #         return False

    def get_public_account(self, instance):
        kwargs = {"many": False, "context": self.context}
        if instance.public_account:
            return PublicAccountSerializers(instance.public_account, **kwargs).data
        else:
            return PublicAccountSerializers(PublicAccount.objects.get(sign="youpinhuiyuan"), **kwargs).data

    def get_level_desc(self, instance):
        return instance.level.get_level_display()

    def get_is_vip(self, instance):
        if instance.level.level > 1:
            return True
        else:
            return False

    def get_user_id(self, instance):
        return instance.id

    def get_leader(self, instance):
        return instance.leader.id if instance.leader else ""

    def get_name(self, instance):
        return instance.name if instance.name else instance.mobile[:3] + "*" * 4 + instance.mobile[7:]

    def get_bank(self, instance):
        serializer = BankCodeSerializer(instance.bank, many=False)
        return serializer.data if instance.bank else ""

    def get_bank_card_no(self, instance):
        return instance.bank_card_no if instance.bank_card_no else ""

    def get_leader_name(self, instance):
        return instance.leader.name if instance.leader else ""

    def get_real_name(self, instance):
        return instance.real_name if instance.real_name else ""

    def get_user_code(self, instance):
        return instance.id

    def get_show_public_account(self, instance):
        if not instance.public_account or instance.public_account.sign == "youpinhuiyuan":
            if instance.wx_user:
                content = wx_base.client.user.get(instance.wx_user.openid)
                if content.get("subscribe") == 1 or content.get("subscribe") == "1":
                    instance.show_public_account = False
                    instance.save()
                    return False
                else:
                    if not instance.show_public_account:
                        instance.show_public_account = True
                        instance.save()
                    return True
            else:
                return instance.show_public_account
        else:
            return instance.show_public_account

    class Meta:
        model = UserModel
        fields = ("id", "user", "user_id", "user_code", "mobile", "lower_num", "bank", "bank_card_no",
                  "leader", "leader_name", "name", "real_name", "header_img", "is_vip", "level_desc",
                  "public_account", "show_qr_code", "show_public_account", "company",
                  "oil_flag", "oil_flag_expiry_date")


# 优秀服务商
class UfSerializers(UserImgSerializers):
    user_code = serializers.SerializerMethodField(label="推荐码")

    def get_user_code(self, instance):
        return instance.id

    class Meta:
        model = UserModel
        fields = ("name", "user_code", "id", "header_img")


# 子菜单
class ChildMenusSerializers(serializers.ModelSerializer):
    class Meta:
        model = Menus
        exclude = ("company",)


# 菜单
class MenusSerializers(serializers.ModelSerializer):
    child_menus = ChildMenusSerializers(many=True)

    class Meta:
        model = Menus
        exclude = ("company",)


# 根据用户id获取昵称
class NickNameSerializers(serializers.ModelSerializer):
    class Meta:
        model = UserModel()
        fields = ("name",)


class PublicAccountSerializers(serializers.ModelSerializer):
    class Meta:
        model = PublicAccount
        fields = "__all__"


# 用户推广图
class PopularSerializers(serializers.ModelSerializer):
    class Meta:
        model = PopularQrCode
        fields = ("url",)
